package com.zofer.study;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.SynchronousQueue;

public class BlockingQueueTest {
    public static void main(String[] args) throws InterruptedException {
//        testLinkedBlockingQueue();
//        testArrayBlockingQueue();
//        testSynchronousQueue();
        testLinkedBlockingDeque();

    }


    /**
     * ArrayBlockingQueue 只能做有界
     */
    public static void testArrayBlockingQueue() throws InterruptedException {
        // 我们创建了一个ArrayBlockingQueue，并且设置队列空间为2
        ArrayBlockingQueue<Object> arrayQueue = new ArrayBlockingQueue<Object>(2);
        // 插入第一个对象
        arrayQueue.put(new Object());

        // 插入第二个对象
        arrayQueue.put(new Object());

        // 插入第三个对象时，这个操作线程就会被阻塞。
        arrayQueue.put(new Object());
        // 请不要使用add操作，和SynchronousQueue的add操作一样，它们都使用了AbstractQueue中的add实现
        System.out.println("===有界===");
    }

    /**
     * LinkedBlockingQueue 可以当做有界和无界
     */
    public static void testLinkedBlockingQueue() throws InterruptedException {
        LinkedBlockingQueue<Object> linkedQueue = new LinkedBlockingQueue<Object>();
        linkedQueue.put(new Object());
        // 插入第二个对象
        linkedQueue.put(new Object());
        // 插入第N个对象时，都不会阻塞
        linkedQueue.put(new Object());
        System.out.println("===无界==");

        LinkedBlockingQueue<Object> blockLinkedQueue = new LinkedBlockingQueue<Object>(2);
        linkedQueue.put(new Object());
        // 插入第二个对象
        linkedQueue.put(new Object());
        // 插入第N个对象时，会阻塞
        linkedQueue.put(new Object());
        System.out.println("===有界==");
    }


    /**
     * LinkedBlockingQueue 无界
     */
    public static void testLinkedBlockingDeque() throws InterruptedException {
        LinkedBlockingDeque<String> linkedDeque = new LinkedBlockingDeque<String>();
        //push 从队头插入
        linkedDeque.push("1");
        // 插入第二个对象
        linkedDeque.put("2");
        // 插入第N个对象时，都不会阻塞
        linkedDeque.put("3");
        System.out.println(linkedDeque.poll());

        //put 队尾插入
        linkedDeque.put("4");
        // 插入第二个对象
        linkedDeque.put("5");
        // 插入第N个对象时，会阻塞
        linkedDeque.put("6");
        System.out.println(linkedDeque.pollLast());
    }

    /**
     * SynchronousQueue
     */
    public static void testSynchronousQueue() throws InterruptedException {
        final SynchronousQueue<String> queue = new SynchronousQueue<String>();

        // 不要使用add，因为这个队列内部没有任何容量，所以会抛出异常“IllegalStateException”
        // queue.add(new Object());

        // 操作线程会在这里被阻塞，直到有其他操作线程取走这个对象
        queue.put("1");

        System.out.println("===不存储元素的阻塞队列==");
    }
}
